package com.soulballad.usage.springcloud.config;

import com.alibaba.cloud.circuitbreaker.sentinel.ReactiveSentinelCircuitBreakerFactory;
import com.alibaba.cloud.circuitbreaker.sentinel.SentinelConfigBuilder;
import com.alibaba.csp.sentinel.adapter.spring.webflux.callback.BlockRequestHandler;
import com.alibaba.csp.sentinel.slots.block.RuleConstant;
import com.alibaba.csp.sentinel.slots.block.degrade.DegradeRule;
import org.springframework.cloud.client.circuitbreaker.Customizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.web.reactive.function.BodyInserters;
import org.springframework.web.reactive.function.server.ServerResponse;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import java.util.Collections;

/**
 * @author ：soulballad
 * @version : v1.0
 * @apiNote : config
 * @since ：2020/6/28 20:58
 */
@Configuration
public class SentinelWebFluxConfig {

    @Bean
    public BlockRequestHandler blockRequestHandler() {
        return new BlockRequestHandler() {
            @Override
            public Mono<ServerResponse> handleRequest(ServerWebExchange exchange, Throwable throwable) {
                return ServerResponse.status(HttpStatus.TOO_MANY_REQUESTS)
                        .contentType(MediaType.APPLICATION_JSON)
                        .body(BodyInserters.fromValue("alb-sentinel-webflux blocked!"));
            }
        };
    }

    @Bean
    public Customizer<ReactiveSentinelCircuitBreakerFactory> slowCustomizer() {
        return factory -> {
            factory.configure(builder -> builder.rules(Collections.singletonList(
                    new DegradeRule("slow_mono").setGrade(RuleConstant.DEGRADE_GRADE_RT)
                            .setCount(100).setTimeWindow(5))
            ), "slow_mono");
            factory.configure(builder -> builder.rules(Collections.singletonList(
                    new DegradeRule("slow_flux").setGrade(RuleConstant.DEGRADE_GRADE_RT)
                            .setCount(100).setTimeWindow(5)
            )), "slow_flux");
            factory.configureDefault(id -> new SentinelConfigBuilder().resourceName(id)
                    .rules(Collections.singletonList(new DegradeRule(id)
                            .setGrade(RuleConstant.DEGRADE_GRADE_EXCEPTION_COUNT)
                            .setCount(0.5).setTimeWindow(5)))
                    .build());
        };
    }
}
